package com.changxianggu.cloud.crawler.core.utils;

import cn.hutool.core.date.DateUtil;
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.poi.ss.usermodel.Workbook;
import org.jboss.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExportExcelUtil {

    private static final Logger logger = Logger.getLogger(ExportExcelUtil.class);

    private static final String TEMPLATE_PATH = "/template";

    /**
     * 导出excel 入口方法 可直接调用
     *
     * @param fileName
     * @param filePath
     * @param dataList
     * @param request
     * @param response
     */
    public static void exportExcel(String fileName, String filePath, List dataList,
                                   HttpServletRequest request, HttpServletResponse response) {
        try (OutputStream out = response.getOutputStream()) {
            // 封装map 生成workbook
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("dataList", dataList);
            Workbook workbook = ExportExcelUtil.exportExcel(filePath, dataMap);
            // 获取文件名称
            StringBuilder s = new StringBuilder(fileName);
            if (s.length() == 0) {
                s.append("导出文件-").append(DateUtil.now());
            } else {
                s.append(DateUtil.now());
            }
            String newFileName = ExportExcelUtil.fileNameHandle(s.toString(), request);
            // 设置内容类型
            response.setContentType("application/vnd.ms-excel");
            // 设置http头信息的内容
            response.addHeader("Content-Disposition", "attachment;filename=\"" + newFileName + "\"");
            workbook.write(out);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 单sheet页导出
     *
     * @param excelName 指向/classes/template/下的相对路径
     * @param dataMap   数据封装map
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static Workbook exportExcel(String excelName, Map<String, Object> dataMap) {
        // String path = getExcelPath(excelName);
        XLSTransformer transformer = new XLSTransformer();
        BufferedInputStream bis = null;
        Workbook workbook = null;
        try {
            // 获取输出流
            // 获得模板的文件输入流
            bis = new BufferedInputStream(ExportExcelUtil.class.getResourceAsStream(excelName));
            // 将数据写入模板
            workbook = transformer.transformXLS(bis, dataMap);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return workbook;
    }

    /**
     * 多sheet页导出
     *
     * @param excelName     模版名称
     * @param dataList      数据集合
     * @param sheetNameList sheet页名称集合
     * @param flagName      标记名称
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static InputStream MultipleSheetsExportExcel(String excelName, List<Object> dataList,
                                                        List<String> sheetNameList, String flagName) {
        // 声明流处理所需变量
        //String path = getExcelPath(excelName);
        XLSTransformer transformer = new XLSTransformer();
        BufferedInputStream bis = null;
        ByteArrayOutputStream os = null;
        InputStream is = null;
        try {
            // 获得模板的文件输入流
            bis = new BufferedInputStream(ExportExcelUtil.class.getResourceAsStream(excelName));
            // 将数据写入模板
            Workbook workbook = transformer.transformMultipleSheetsList(bis, dataList, sheetNameList,
                    flagName, new HashMap(), 0);
            // 获取输出流
            os = new ByteArrayOutputStream();
            // 将workbook用输出流输出
            workbook.write(os);
            is = new ByteArrayInputStream(os.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return is;
    }

    /**
     * 获取excel模版绝对路径
     *
     * @param excelName 指向/classes/template/下的相对路径
     * @return
     * @see [类、类#方法、类#成员]
     */
    @Deprecated
    public static String getExcelPath(String excelName) {
        // 获取classpath 路径
        String classPath = ExportExcelUtil.class.getResource("/").getPath();
        StringBuilder path = new StringBuilder();
        path.append(classPath).append(TEMPLATE_PATH).append(File.separator).append(excelName);
        return path.toString();
    }

    /**
     * 处理文件名称中文编码问题
     *
     * @param fileName 文件名称
     * @param request
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String fileNameHandle(String fileName, HttpServletRequest request)
            throws UnsupportedEncodingException {
        // 处理文件名称后缀名
        int index = fileName.lastIndexOf(".");
        if (index == -1) {
            fileName += ".xlsx";
        } else {
            String suffix = fileName.substring(index);
            if (!".xls".equals(suffix) && !".xlsx".equals(suffix)) {
                fileName += ".xlsx";
            }
        }
        // 兼容浏览器处理中文乱码
        String Agent = request.getHeader("User-Agent");
        if (null != Agent) {
            // Firefox
            if (-1 != Agent.indexOf("Firefox")) {
                fileName = "=?UTF-8?B?"
                        + (new String(org.apache.commons.codec.binary.Base64.encodeBase64(fileName.getBytes("UTF-8"))))
                        + "?=";
            } else if (-1 != Agent.indexOf("Chrome")) { // Google
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else { // IE7+
                fileName = URLEncoder.encode(fileName, "UTF-8");
            }
        }
        return fileName;
    }

}
